package com.example.demo.thread.lock.reentrant;

/**
 * 可重入锁 测试
 *
 * 如果锁具备可重入性，则称作为可重入锁。像synchronized和ReentrantLock都是可重入锁，
 * 可重入性在我看来实际上表明了锁的分配机制：基于线程的分配，而不是基于方法调用的分配。
 * 举个简单的例子，当一个线程执行到某个synchronized方法时，比如说method1，
 * 而在method1中会调用另外一个synchronized方法method2，此时线程不必重新去申请锁，而是可以直接执行方法method2。
 *
 * 上述代码中的两个方法method1和method2都用synchronized修饰了，
 * 假如某一时刻，线程A执行到了method1，此时线程A获取了这个对象的锁，而由于method2也是synchronized方法，
 * 假如synchronized不具备可重入性，此时线程A需要重新申请锁。但是这就会造成一个问题，
 * 因为线程A已经持有了该对象的锁，而又在申请获取该对象的锁，这样就会线程A一直等待永远不会获取到的锁。
 *
 * @author Roger
 * @since 2021/6/29
 */
public class ReentrantSync {

    public synchronized void method1(String threadId) {
        System.out.println(threadId+"-----开始锁1----");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        method2(threadId);
        System.out.println(threadId+"-----结束锁1----");
    }

    public synchronized void method2(String threadId) {
        System.out.println(threadId+"-----开始锁2----");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(threadId+"-----结束锁2----");
    }

    public static void main(String[] args){
        ReentrantSync synchronizedTest = new ReentrantSync();
        new Thread(){
            public void run() {
                synchronizedTest.method1(Thread.currentThread().getName());
            };
        }.start();

        new Thread(){
            public void run() {
                synchronizedTest.method1(Thread.currentThread().getName());
            };
        }.start();
    }

}
